
/*
	http://www.openjs.com/scripts/events/keyboard_shortcuts/
	
	
	name
	toString
	
	add
	remove
	
	compatible
	
	defaultKeyEvent
	crateKeyEvent
	removeKeyEvent
	findKeyCode
	KEYGROUPS
	isEvent

	create
	fire
	events
	
	
	
*/

var Event={
	name:"Event",
	toString:function(){
		return this.name;
	},
	add:function(ev, fu, ob, bu){
		
		 if(!this.isEvent(ev) && !fu.KeyEventBind){
			var c = this.createKeyEvent(ev, fu, ob);
			ev = c.e;
			fu = c.f;
		 };
		
		if(ob.attachEvent){
			if(	!fu.EventBind ){ 
				fu.EventBind = function(e){
					var f = arguments.callee;
						f.Base.compatible(e);
						f.Function.call(f.Scope, e);
				};
				fu.EventBind.toString = function(){return this.Function.toString();};
				fu.EventBind.Scope = ob;
				fu.EventBind.Function = fu;
				fu.EventBind.Base = this;
			};
			return ob.attachEvent("on"+ev, fu.EventBind || fu);
		}else if(ob.addEventListener){
			return ob.addEventListener(ev,fu,bu||false);
		}else{
			ob["on"+ev] = fu;
			return true;
		};
		return false;
	},	
	remove:function(ev, fu, ob, bu){
		
		if(!this.isEvent(ev)){
			var c = this.removeKeyEvent(ev, fu, ob);
			ev = c.e;
			fu = c.f;
		};
		
		if(ob.detachEvent){
			if(fu.EventBind){
				ob.detachEvent("on"+ev, fu.EventBind);
				delete fu.EventBind;
			}else{
				ob.detachEvent("on"+ev, fu);
			}
			return true;
		}else if(ob.removeEventListener){
			ob.removeEventListener(ev,fu,bu||false);
			return true;
		}else{
			ob["on"+ev] = null;
			return true;
		};
		return false;
	},
	compatible:function(e){
		if(window.addEventListener) return false;
		
		e.preventDefault = function(){	return this.returnValue = false;	}
		e.stopPropagation = function(){	return this.cancelBubble = true;	}
		e.target = e.srcElement;
		e.relatedTarget = e.fromElement;
		e.timeStamp = new Date().getTime();
		
		return 	e;
	},
	
	defaultKeyEvent:"keydown",
	createKeyEvent:function(ev, fu, ob){
		var z="", g={};
		if(this.KEYGROUPS.hasOwnProperty(ev)){
			g = this.KEYGROUPS[ev];
			z = "f.Group.hasOwnProperty(e.keyCode)";
		}else{
			for(var i=0, e=ev.split("+"), o=""; i < e.length; i++){
				switch(e[i].toUpperCase()){
					case "CTRL":	z += "e.ctrlKey" + o; break;
					case "ALT":		z += "e.altKey" + o; break;
					case "SHIFT":	z += "e.shiftKey" + o; break;
					default:		z += "e.keyCode==" + this.findKeyCode(e[i]) + o; break;
				}
				z += i<e.length-1 ? "&&" : "";
			}
		}
		fu.KeyEventBind = new Function("e","var f=arguments.callee, c=f.Group[e.keyCode]; if(" + z + "){f.Base.compatible(e);return f.Function.call(f.Scope, e, c);}")
		fu.KeyEventBind.Scope = ob;
		fu.KeyEventBind.Group = g;
		fu.KeyEventBind.Function = fu;
		fu.KeyEventBind.Base = this;
		return {e:this.defaultKeyEvent, f:fu.KeyEventBind};
	},
	removeKeyEvent:function(ev, fu){
		delete fu.KeyEventBind;
		return {e:this.defaultKeyEvent, f:fu};
	},
	findKeyCode:function(k){
		var a, b, g = this.KEYGROUPS;
		for(a in g){
			for(b in g[a]){
				if(g[a][b] == k){
					return b;
				}
			}
		}
	},
	KEYGROUPS:{
		BACKSPACE:{8:"BACKSPACE"},
		TAB:{9:"TAB"},
		ENTER:{13:"ENTER"},
		ESQ:{27:"ESQ"},
		SPACE:{32:"SPACE"},
		END:{35:"END"},
		PAGEUP:{33:"PAGEUP"},
		PAGEDOWN:{34:"PAGEDOWN"},
		HOME:{36:"HOME"},
		LEFT:{37:"LEFT"},
		ARROWS:{37:"LEFT",38:"UP",39:"RIGHT",40:"DOWN"},
		UP:{38:"UP"},
		RIGHT:{39:"RIGHT"},
		DOWN:{40:"DOWN"},
		INSERT:{45:"INSERT"},
		DELETE:{46:"DELETE"},
		NUMBERS:{48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"},
		CHARACTERS:{65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z"},
		MATHNUMBERS:{96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"},
		MATHOPERATORS:{106:"*",107:"+",109:"-",111:"/"},
		HELP:{112:"F1"},
		FUNCTIONS:{112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12"}
	},
	isEvent:function(ev){
		return /^(abort|blur|change|error|focus|load|reset|resize|scroll|select|submit|unload|key|click|dbl|mouse|DOM)/gi.test(ev);
	},
	create:function(){
		var type=arguments[0], groupName, group, r=new RegExp("(^|,)"+type+"(,|$)","i");
		for(groupName in this.events){
			if(r.test(this.events[groupName].type.toString())){
				group = this.events[groupName];
				break;
			}
		}
		var e = document.createEvent(groupName);
		if(arguments.length < group.args.length){
			var a=[], args=arguments;
			group.args.forEach(function(o,i){
				a[i] = args[i] || o;
			})
		}
		e[group.init].apply(e,a);
		return e;
	},
	fire:function(type,o){
		o.dispatchEvent(this.create(type));
	},
	events:{
		//event.initUIEvent(type, canBubble, cancelable)
		//event.initUIEvent(type, canBubble, cancelable, view, detail)
		//event.initMouseEvent(type, canBubble, cancelable, view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
		//event.initMutationEvent(typeArg, canBubbleArg, cancelableArg, relatedNodeArg, prevValueArg, newValueArg, attrNameArg, attrChangeArg )
		"HTMLEvents":{
			init:"initEvent",
			type:['abort','blur','change','error','focus','load','reset','resize','scroll','select','submit','unload'],
			args:["type",true,true]
		},
		"UIEvents":{
			init:"initUIEvent",
			type:['DOMActivate','DOMFocusIn','DOMFocusOut','keydown','keypress','keyup'],
			args:["type",true,true,window,1]
		},
		"MouseEvents":{
			init:"initMouseEvent",
			type:['click','mousedown','mousemove','mouseout','mouseover','mouseup'],
			args:["type",true,true,window,0,0,0,0,0,false,false,false,false,0,null]
		},
		"MutationEvents":{
			init:"initMutationEvent",
			type:['DOMAttrModified','DOMNodeInserted','DOMNodeRemoved','DOMCharacterDataModified','DOMNodeInsertedIntoDocument','DOMNodeRemovedFromDocument','DOMSubtreeModified'],
			args:["type",true,true]
		}
	}
}


